package com.moxie.liveness.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import static android.content.Context.SENSOR_SERVICE;

public class MXSensorManager {

    private SensorManager mSM = null;
    public MXSensorManager(Context context) {
        mSM = (SensorManager) context.getSystemService(SENSOR_SERVICE);
    }

    public void registerListener(SensorEventListener listener) {
        mSM.registerListener(listener, mSM.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
        mSM.registerListener(listener, mSM.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR), SensorManager.SENSOR_DELAY_UI);
        mSM.registerListener(listener, mSM.getDefaultSensor(Sensor.TYPE_GRAVITY), SensorManager.SENSOR_DELAY_UI);
        mSM.registerListener(listener, mSM.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
    }

    public void unregisterListener(SensorEventListener listener) {
        mSM.unregisterListener(listener);
    }

    public static class MXSDCardUtils {
        public static String TAG = MXSDCardUtils.class.getSimpleName();
        // 判断SD卡是否被挂载
        public static boolean isSDCardMounted() {
            // return Environment.getExternalStorageState().equals("mounted");
            return Environment.getExternalStorageState().equals(
                    Environment.MEDIA_MOUNTED);
        }

        // 获取SD卡的根目录
        public static String getSDCardBaseDir() {
            if (isSDCardMounted()) {
                return Environment.getExternalStorageDirectory().getAbsolutePath();
            }
            return null;
        }

        // 获取SD卡的完整空间大小，返回MB
        public static long getSDCardSize() {
            if (isSDCardMounted()) {
                StatFs fs = new StatFs(getSDCardBaseDir());
                long count = fs.getBlockCountLong();
                long size = fs.getBlockSizeLong();
                return count * size / 1024 / 1024;
            }
            return 0;
        }

        // 获取SD卡的剩余空间大小
        public static long getSDCardFreeSize() {
            if (isSDCardMounted()) {
                StatFs fs = new StatFs(getSDCardBaseDir());
                long count = fs.getFreeBlocksLong();
                long size = fs.getBlockSizeLong();
                return count * size / 1024 / 1024;
            }
            return 0;
        }

        // 获取SD卡的可用空间大小
        public static long getSDCardAvailableSize() {
            if (isSDCardMounted()) {
                StatFs fs = new StatFs(getSDCardBaseDir());
                long count = fs.getAvailableBlocksLong();
                long size = fs.getBlockSizeLong();
                return count * size / 1024 / 1024;
            }
            return 0;
        }

        // 往SD卡的公有目录下保存文件
        public static boolean saveFileToSDCardPublicDir(byte[] data, String type, String fileName) {
            BufferedOutputStream bos = null;
            if (isSDCardMounted()) {
                File file = Environment.getExternalStoragePublicDirectory(type);
                try {
                    bos = new BufferedOutputStream(new FileOutputStream(new File(file, fileName)));
                    bos.write(data);
                    bos.flush();
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        bos.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            return false;
        }

        // 往SD卡的自定义目录下保存文件
        public static boolean saveFileToSDCardCustomDir(byte[] data, String dir, String fileName) {
            FileOutputStream bos = null;
            if (isSDCardMounted()) {
                File file = new File(getSDCardBaseDir() + File.separator + dir);
                if (!file.exists()) {
                    file.mkdirs();// 递归创建自定义目录
                }
                try {
                    File newFile = new File(file,fileName);
                    bos = new FileOutputStream(newFile);
                    bos.write(data);
                    bos.flush();
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (bos != null)
                            bos.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            return false;
        }

        // 往SD卡的私有Files目录下保存文件
        public static boolean saveFileToSDCardPrivateFilesDir(byte[] data, String type, String fileName, Context context) {
            BufferedOutputStream bos = null;
            if (isSDCardMounted()) {
                File file = context.getExternalFilesDir(type);
                try {
                    bos = new BufferedOutputStream(new FileOutputStream(new File(file, fileName)));
                    bos.write(data);
                    bos.flush();
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        bos.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            return false;
        }

        // 往SD卡的私有Cache目录下保存文件
        public static boolean saveFileToSDCardPrivateCacheDir(byte[] data, String fileName, Context context) {
            BufferedOutputStream bos = null;
            if (isSDCardMounted()) {
                File file = context.getExternalCacheDir();
                try {
                    bos = new BufferedOutputStream(new FileOutputStream(new File(file, fileName)));
                    bos.write(data);
                    bos.flush();
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        bos.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            return false;
        }

        /**
         * 保存String到文件
         * @param file  目标文件
         * @param source  数据源
         * @return  返回boolean
         */
        public static boolean saveFile(File file, String source) {
            boolean isSuccess = true;

            if (source != null) {
                try {
                    copyFileUsingFileStreams(source.getBytes(), file);
                } catch (IOException e) {
                    isSuccess = false;
                    e.printStackTrace();
                }
            }
            return isSuccess;
        }

        /**
         * 保存byte[]到文件
         * @param file  目标文件
         * @param sourceFile   数据源
         * @return  返回boolean
         */
        public static boolean saveFile(File file, byte[] sourceFile) {
            boolean isSuccess = true;

            if (sourceFile != null) {
                try {
                    copyFileUsingFileStreams(sourceFile, file);
                } catch (IOException e) {
                    isSuccess = false;
                    e.printStackTrace();
                }
            }
            return isSuccess;
        }

        /**
         * 将byte[]写入到文件
         * @param source 数据源
         * @param dest  目标文件
         * @throws IOException
         */
        private static void copyFileUsingFileStreams(byte[] source, File dest)
                throws IOException {
            ByteArrayInputStream inputStream = new ByteArrayInputStream(source);
            OutputStream output = null;
            if (!dest.exists()) {
                dest.getParentFile().mkdirs();
            }
            try {
                output = new FileOutputStream(dest);
                byte[] buf = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buf)) > 0) {
                    output.write(buf, 0, bytesRead);
                }
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (output != null) {
                    output.close();
                }
            }
        }

        /**
         * 复制单个文件
         * @param oldPath String 原文件路径 如：c:/fqf.txt
         * @param newPath String 复制后路径 如：f:/fqf.txt
         * @return boolean
         */
        public static boolean copyFile(String oldPath, String newPath) {
            try {
                int bytesum = 0;
                int byteread = 0;
                File oldfile = new File(oldPath);
                File newfile = new File(newPath);
                if (!newfile.exists()) {
                    newfile.getParentFile().mkdirs();
                }
                if (oldfile.exists()) { //文件存在时
                    InputStream inStream = new FileInputStream(oldPath); //读入原文件
                    FileOutputStream fs = new FileOutputStream(newPath);
                    byte[] buffer = new byte[1444];
                    int length;
                    while ( (byteread = inStream.read(buffer)) != -1) {
                        bytesum += byteread; //字节数 文件大小
                        fs.write(buffer, 0, byteread);
                    }
                    inStream.close();
                    return true;
                } else {
                    return false;
                }
            }
            catch (Exception e) {
                e.printStackTrace();
                return false;
            }

        }

        // 保存bitmap图片到SDCard的私有Cache目录
        public static boolean saveBitmapToSDCardPrivateCacheDir(Bitmap bitmap, String fileName, Context context) {
            if (isSDCardMounted()) {
                BufferedOutputStream bos = null;
                // 获取私有的Cache缓存目录
                File file = context.getExternalCacheDir();

                try {
                    bos = new BufferedOutputStream(new FileOutputStream(new File(file, fileName)));
                    if (fileName != null && (fileName.contains(".png") || fileName.contains(".PNG"))) {
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
                    } else {
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
                    }
                    bos.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (bos != null) {
                        try {
                            bos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                return true;
            } else {
                return false;
            }
        }

        // 从SD卡获取文件
        public static byte[] loadFileFromSDCard(String fileDir) {
            BufferedInputStream bis = null;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            try {
                bis = new BufferedInputStream(new FileInputStream(new File(fileDir)));
                byte[] buffer = new byte[8 * 1024];
                int c = 0;
                while ((c = bis.read(buffer)) != -1) {
                    baos.write(buffer, 0, c);
                    baos.flush();
                }
                return baos.toByteArray();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    baos.close();
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        // 从SDCard中寻找指定目录下的文件，返回Bitmap
        public Bitmap loadBitmapFromSDCard(String filePath) {
            byte[] data = loadFileFromSDCard(filePath);
            if (data != null) {
                Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
                if (bm != null) {
                    return bm;
                }
            }
            return null;
        }

        // 获取SD卡公有目录的路径
        public static String getSDCardPublicDir(String type) {
            return Environment.getExternalStoragePublicDirectory(type).toString();
        }

        // 获取SD卡私有Cache目录的路径
        public static String getSDCardPrivateCacheDir(Context context) {
            return context.getExternalCacheDir().getAbsolutePath();
        }

        // 获取SD卡私有Files目录的路径
        public static String getSDCardPrivateFilesDir(Context context, String type) {
            return context.getExternalFilesDir(type).getAbsolutePath();
        }

        public static boolean isFileExist(String filePath) {
            File file = new File(filePath);
            return file.isFile();
        }

        // 从sdcard中删除文件
        public static boolean removeFileFromSDCard(String filePath) {
            File file = new File(filePath);
            if (file.exists()) {
                try {
                    file.delete();
                    return true;
                } catch (Exception e) {
                    return false;
                }
            } else {
                return false;
            }
        }

        /**
         * flie：要删除的文件夹的所在位置
         * @param file
         */
        public static void deleteFile(File file) {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                for (int i = 0; i < files.length; i++) {
                    File f = files[i];
                    deleteFile(f);
                }
                file.delete();//如要保留文件夹，只删除文件，请注释这行
            } else if (file.exists()) {
                file.delete();
            }
        }
    }

    public static class MXLog {
        private static boolean sIsDebug = false;
        private static String STAG = "mx_log";

        public static final int LOG_MESSAGE_MAX_LENGTH = 100;

        public static void init(boolean isDebug, String logTag) {
            sIsDebug = isDebug;
            if (TextUtils.isEmpty(logTag)) {
                STAG = logTag;
            }
        }

        private static boolean isCanLog() {
            return sIsDebug;
        }

        public static void d(Object... message) {
            if (isCanLog()) {
                Log.d(STAG, getLogcat(message));
            }
        }

        @Deprecated
        public static void d(int... message) {
            if (isCanLog()) {
                Log.d(STAG, getLogMessage(String.valueOf(message)));
            }
        }

        public static void i(Object... message) {
            if (isCanLog()) {
                Log.i(STAG, getLogcat(message));
            }
        }

        @Deprecated
        public static void i(int message) {
            if (isCanLog()) {
                Log.i(STAG, getLogMessage(String.valueOf(message)));
            }
        }

        public static void w(Object... message) {
            if (isCanLog()) {
                Log.w(STAG, getLogcat(message));
            }
        }

        @Deprecated
        public static void w(int message) {
            if (isCanLog()) {
                Log.w(STAG, getLogMessage(String.valueOf(message)));
            }
        }

        public static void e(Object... message) {
            if (isCanLog()) {
                Log.e(STAG, getLogcat(message));
            }
        }

        @Deprecated
        public static void e(int message) {
            if (isCanLog()) {
                Log.e(STAG, getLogMessage(String.valueOf(message)));
            }
        }

        public static String getLogcat(Object... message) {
            StringBuilder sb = new StringBuilder();
            if (message != null) {
                for (Object object : message) {
                    sb.append("*******");
                    sb.append(object);
                }
            }
            return sb.toString();
        }

        private static String getPartString(StringBuilder sb) {
            String result = "";
            if (sb != null) {
                if (sb.length() > LOG_MESSAGE_MAX_LENGTH) {
                    StringBuilder partSb = new StringBuilder();
                    int index = 0;
                    while (sb.length() > LOG_MESSAGE_MAX_LENGTH * index) {
                        int subEndIndex = 0;
                        if (LOG_MESSAGE_MAX_LENGTH * (index + 1) > sb.length()) {
                            subEndIndex = sb.length();
                        } else {
                            subEndIndex = LOG_MESSAGE_MAX_LENGTH * (index + 1);
                        }
                        partSb.append(sb.substring(LOG_MESSAGE_MAX_LENGTH * index, subEndIndex));
                        index++;
                    }
                    result = partSb.toString();
                } else {
                    result = sb.toString();
                }
            }
            return result;
        }

        public static String getLogMessage(String message) {
            return "time**".concat("**").concat(message);
        }
    }

    /**
     * MS5
     */
    public static class MD5Util {
        private static final String TAG = MD5Util.class.getSimpleName();
        private static final int STREAM_BUFFER_LENGTH = 1024;

        public static MessageDigest getDigest(final String algorithm) throws NoSuchAlgorithmException {
            return MessageDigest.getInstance(algorithm);
        }

        public static byte[] md5(String txt) {
            return md5(txt.getBytes());
        }

        public static byte[] md5(byte[] bytes) {
            try {
                MessageDigest digest = getDigest("MD5");
                digest.update(bytes);
                return digest.digest();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return null;
        }

        public static byte[] md5(InputStream is) throws NoSuchAlgorithmException, IOException {
            return updateDigest(getDigest("MD5"), is).digest();
        }

        public static MessageDigest updateDigest(final MessageDigest digest, final InputStream data) throws IOException {
            final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
            int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);

            while (read > -1) {
                digest.update(buffer, 0, read);
                read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
            }

            return digest;
        }

        public static String MD5(String sourceStr) {
            String result = "";
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                md.update(sourceStr.getBytes());
                byte b[] = md.digest();
                int i;
                StringBuffer buf = new StringBuffer("");
                for (int offset = 0; offset < b.length; offset++) {
                    i = b[offset];
                    if (i < 0)
                        i += 256;
                    if (i < 16)
                        buf.append("0");
                    buf.append(Integer.toHexString(i));
                }
                result = buf.toString();
            } catch (NoSuchAlgorithmException e) {
                System.out.println(e);
            }
            return result;
        }
    }
}
